#include "chatdialog.h"
#include <QIcon>
#include <QPainter>
#include <QScrollBar>
#include <QStyleOption>
#include <QTimer>
#include <QWheelEvent>
#include "applyfriend.h"
#include "applyfriendpage.h"
#include "chatpage.h"
#include "chatuserwid.h"
#include "contactlist.h"
#include "friendinfopage.h"
#include "loadingdlg.h"
#include "redpointlabel.h"
#include "searchresultlist.h"
#include "tcpmgr.h"
#include "ui_chatdialog.h"
#include "usermgr.h"
ChatDialog::ChatDialog(QWidget *parent)
    : QDialog(parent)
    , ui(new Ui::ChatDialog)
    , _b_loading(false)
{
    ui->setupUi(this);
    // 设置聊天页面为默认显示页面
    ui->chatdlg_left_stacked_widget->setCurrentWidget(ui->chat_page);
    ui->chatdlg_right_stacked_widget->setCurrentWidget(ui->page);
    ui->side_head_lb->setScaledContents(true);
    ui->side_chat_lb->setScaledContents(true);
    ui->side_contact_lb->setScaledContents(true);
    // 用户头像图标
    ui->side_head_lb->setPixmap(QPixmap(":/icon/icon/papaya.png"));
    ui->side_chat_lb->setPixmap(QPixmap(":/icon/icon/bubble_select"));
    ui->side_contact_lb->setPixmap(QPixmap(":/icon/icon/contact_list.png"));
    ui->side_chat_lb->installEventFilter(this);
    ui->side_contact_lb->installEventFilter(this);

    ui->search_edit->setMaxLength(24);
    QAction *search_act = new QAction(ui->search_edit);
    search_act->setIcon(QIcon(":/icon/icon/search.png"));
    QAction *clear_act = new QAction(ui->search_edit);
    clear_act->setIcon(QIcon(":/icon/icon/clear.png"));
    ui->search_edit->addAction(search_act, QLineEdit::LeadingPosition);
    ui->search_edit->addAction(clear_act, QLineEdit::TrailingPosition);
    clear_act->setVisible(false);
    // 清除搜索框内容
    connect(clear_act, &QAction::triggered, this, [this](bool checked) {
        Q_UNUSED(checked);
        ui->search_edit->clear();
    });
    // 关闭联系人列表滚动条
    ui->chat_user_list->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
    ui->chat_user_list->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOn);
    ui->chat_user_list->verticalScrollBar()->setVisible(false);
    ui->chat_user_list->setAutoScroll(true);
    ui->chat_user_list->installEventFilter(this);
    ui->search_edit->installEventFilter(this);
    connect(this, &ChatDialog::sig_loading_chat_user, this, &ChatDialog::slot_loading_chat_user);
    ui->search_list->setSearchEdit(ui->search_edit);
    // 收到好友申请
    connect(TcpMgr::GetInstance().get(),
            &TcpMgr::sig_friendApply,
            this,
            &ChatDialog::slot_addFriendApply);

    connect(ui->friend_apply_page,
            &ApplyFriendPage::sig_hasNewFriendApply,
            ui->side_contact_lb,
            &RedPointLabel::slot_RedPointVisible);

    connect(ui->friend_apply_page,
            &ApplyFriendPage::sig_hasNewFriendApply,
            ui->contact_list,
            &ContactList::sig_newFriendRedPointVisible);

    connect(ui->friend_apply_page,
            &ApplyFriendPage::sig_hasNewFriendApply,
            ui->search_list,
            &SearchResultList::slot_RedPointVisible);
    // 显示好友信息
    connect(ui->contact_list,
            &ContactList::sig_friendClicked,
            this,
            &ChatDialog::slot_showFriendInfo);
    // 页面加载时，提示是否有未添加好友
    if (ui->friend_apply_page->hasUnAuthenFriend()) {
        ui->side_contact_lb->slot_RedPointVisible(true);
        ui->search_list->slot_RedPointVisible(true);
        emit ui->contact_list->sig_newFriendRedPointVisible(true);
    }

    connect(ui->contact_list, &ContactList::sig_showFriendApplyPage, this, [this]() {
        ui->chatdlg_right_stacked_widget->setCurrentWidget(ui->friend_apply_page);
    });
    // 聊天页面跳转
    connect(ui->friend_info_page,
            &FriendInfoPage::sig_messageBtnClicked,
            this,
            &ChatDialog::slot_jumpFriendChatPage);

    // 有新消息
    connect(TcpMgr::GetInstance().get(),
            &TcpMgr::sig_hasNewTextMessage,
            this,
            &ChatDialog::slot_hasNewTextMessage);
    // 初始化聊天页面布局
    chat_msg_page_layout = new QVBoxLayout(ui->chat_msg_page);
    chat_msg_page_layout->setContentsMargins(0, 0, 0, 0);
    chat_msg_page_layout->setSpacing(0);
    // 加载消息
    loadUnreceivedMessage();
}

ChatDialog::~ChatDialog()
{
    delete ui;
}

void ChatDialog::on_search_edit_textChanged(const QString &arg1)
{
    if (ui->chatdlg_left_stacked_widget->currentWidget() != ui->search_result_page) {
        ui->chatdlg_left_stacked_widget->setCurrentWidget(ui->search_result_page);
        ui->chatdlg_right_stacked_widget->setCurrentWidget(ui->friend_apply_page);
    }
    auto acts = ui->search_edit->actions();
    QAction *act = acts.last();
    if (arg1.length() > 0) {
        act->setVisible(true);
    } else {
        act->setVisible(false);
    }
}

bool ChatDialog::eventFilter(QObject *watched, QEvent *event)
{
    // 根据鼠标进入和离开设置滚动条样式
    if (watched == ui->chat_user_list) {
        if (event->type() == QEvent::Enter) {
            ui->chat_user_list->verticalScrollBar()->setVisible(true);
        } else if (event->type() == QEvent::Leave) {
            ui->chat_user_list->verticalScrollBar()->setVisible(false);
        } else if (event->type() == QEvent::Wheel) {
            // 检测是否为鼠标滚动事件
            QWheelEvent *wheelEvent = dynamic_cast<QWheelEvent *>(event);
            int numDegrees = wheelEvent->angleDelta().y() / 8;
            int numSteps = numDegrees / 15;
            // 设置滚动幅度
            ui->chat_user_list->verticalScrollBar()->setValue(
                ui->chat_user_list->verticalScrollBar()->value() - numSteps);
            // 检查是否滚动到底部
            QScrollBar *scrollBar = ui->chat_user_list->verticalScrollBar();
            int maxScrollValue = scrollBar->maximum();
            int currentValue = scrollBar->value();
            if (maxScrollValue - currentValue <= 0) {
                qDebug() << "load more chat user";
                emit sig_loading_chat_user();
            }
        }
        return QWidget::eventFilter(watched, event);
    }

    // 监听搜索输入框失去焦点事件
    if (watched == ui->search_edit && event->type() == QEvent::FocusOut) {
        if (ui->search_edit->text().isEmpty()) {
            ui->chatdlg_left_stacked_widget->setCurrentWidget(ui->chat_page);
            ui->chatdlg_right_stacked_widget->setCurrentWidget(ui->chat_msg_page);
        }
    }
    //
    if (watched == ui->side_chat_lb && event->type() == QEvent::MouseButtonPress) {
        ui->search_edit->clear();
        ui->chatdlg_left_stacked_widget->setCurrentWidget(ui->chat_page);
        ui->chatdlg_right_stacked_widget->setCurrentWidget(ui->chat_msg_page);
        ui->side_chat_lb->setPixmap(QPixmap(":/icon/icon/bubble_select.png"));
    }
    // 联系人列表
    if (watched == ui->side_contact_lb && event->type() == QEvent::MouseButtonPress) {
        ui->search_edit->clear();
        ui->chatdlg_left_stacked_widget->setCurrentWidget(ui->contact_page);
        ui->side_contact_lb->setPixmap(QPixmap(":/icon/icon/contact_list_hover.png"));
    }

    return QWidget::eventFilter(watched, event);
}

void ChatDialog::addChatUserList()
{
    // 是否加载完所有聊天记录
    if (UserMgr::GetInstance()->IsLoadChatFinish())
        return;
    auto chatList = UserMgr::GetInstance()->GetChatListPerPage();
    // 更新加载条目
    UserMgr::GetInstance()->UpdateChatLoadedCount();
    if (chatList.isEmpty())
        return;
    for (auto &friendInfo : chatList) {
        appendChatUserItem(friendInfo);
    }
}

void ChatDialog::handleGlobalMousePress(QMouseEvent *event)
{
    // 是否处于搜索模式
    if (ui->chatdlg_left_stacked_widget->currentWidget() != ui->search_result_page) {
        return;
    }
    // 获取鼠标点击位置
    QPoint posInSearchList = ui->search_list->mapFromGlobal(event->pos());
    // 判断点击位置是否在搜索结果列表范围内
    if (!ui->search_list->rect().contains(posInSearchList)) {
        ui->search_list->hide();
        ui->search_list->deleteLater();
        ui->chatdlg_left_stacked_widget->setCurrentWidget(ui->chat_page);
        ui->chatdlg_right_stacked_widget->setCurrentWidget(ui->chat_msg_page);
    }
}

QListWidgetItem *ChatDialog::findChatUserItem(int uid)
{
    auto iter = _chatUserMap.find(uid);
    if (iter == _chatUserMap.end()) {
        return nullptr;
    }
    return iter.value();
}

QListWidgetItem *ChatDialog::insertChatUserItem(int row,
                                                std::shared_ptr<FriendInfo> friendInfo,
                                                bool showRedPoint)
{
    auto iter = _chatUserMap.find(friendInfo->uid);
    if (iter != _chatUserMap.end()) {
        return nullptr;
    }
    ChatUserWid *chatItem = new ChatUserWid(ui->chat_user_list);
    connect(chatItem, &ChatUserWid::sig_clicked, this, &ChatDialog::slot_charUserClicked);
    chatItem->setChatInfo(friendInfo);
    chatItem->setRedPointVisible(showRedPoint);
    chatItem->adjustSize();
    QListWidgetItem *item = new QListWidgetItem();
    item->setSizeHint(chatItem->size());
    ui->chat_user_list->insertItem(row, item);
    ui->chat_user_list->setItemWidget(item, chatItem);
    ui->chat_user_list->adjustSize();
    _chatUserMap[friendInfo->uid] = item;
    return item;
}

void ChatDialog::removeChatUserItem(int uid)
{
    QListWidgetItem *item = findChatUserItem(uid);
    ui->chat_user_list->itemWidget(item)->deleteLater();
    ui->chat_user_list->removeItemWidget(item);
    delete item;
    _chatUserMap.remove(uid);
}

QListWidgetItem *ChatDialog::makeChatUserFirst(std::shared_ptr<FriendInfo> friendInfo,
                                               bool showRedPoint)
{
    // 查看当前聊天页面是否包含该信息
    QListWidgetItem *item = findChatUserItem(friendInfo->uid);
    // 空指针，不存在该聊天记录
    if (!item) {
        // 创建聊天记录，将其插入第一个位置
        item = insertChatUserItem(0, friendInfo, showRedPoint);
    } else {
        // 从原始位置删除，插入到第一行
        removeChatUserItem(friendInfo->uid);
        item = insertChatUserItem(0, friendInfo, showRedPoint);
    }
    return item;
}

void ChatDialog::showChatPage(std::shared_ptr<FriendInfo> friendInfo)
{
    // 清空当前显示页面
    while (chat_msg_page_layout->count() > 0) {
        chat_msg_page_layout->takeAt(0);
    }
    auto friendPageiter = _friendPages.find(friendInfo->uid);
    // 不存在与该用户的聊天界面
    if (friendPageiter == _friendPages.end()) {
        auto chatPage = std::make_shared<ChatPage>(ui->chat_msg_page);
        chatPage->setFriendInfo(friendInfo);
        chatPage->adjustSize();
        // 加入列表
        _friendPages[friendInfo->uid] = chatPage;
        // 将当前页面加入布局中
        chat_msg_page_layout->addWidget(chatPage.get());
    } else {
        chat_msg_page_layout->addWidget(friendPageiter.value().get());
    }
    // 右侧显示连天信息界面
    ui->chatdlg_right_stacked_widget->setCurrentWidget(ui->chat_msg_page);
}

void ChatDialog::loadUnreceivedMessage()
{
    QVector<std::shared_ptr<TextChatData>> unreceivedMessageList = UserMgr::GetInstance()
                                                                       ->GetUnreceivedMessageList();
    if (unreceivedMessageList.empty()) {
        return;
    }
    for (auto &message : unreceivedMessageList) {
        slot_hasNewTextMessage(message);
    }
}

void ChatDialog::appendChatUserItem(std::shared_ptr<FriendInfo> friendInfo)
{
    int chatUserCount = _chatUserMap.size();
    insertChatUserItem(chatUserCount, friendInfo);
}

void ChatDialog::on_chatdlg_left_stacked_widget_currentChanged(int arg1)
{
    // chat_page
    if (arg1 == 0) {
        ui->side_contact_lb->setPixmap(QPixmap(":/icon/icon/contact_list.png"));
        ui->side_chat_lb->setPixmap(QPixmap(":/icon/icon/bubble_select.png"));
    }
    // search_result_page
    if (arg1 == 1) {
        ui->side_chat_lb->setPixmap(QPixmap(":/icon/icon/bubble.png"));
        ui->side_contact_lb->setPixmap(QPixmap(":/icon/icon/contact_list.png"));
    }
    // contact_page
    if (arg1 == 2) {
        ui->side_chat_lb->setPixmap(QPixmap(":/icon/icon/bubble.png"));
        ui->side_contact_lb->setPixmap(QPixmap(":/icon/icon/contact_list_hover.png"));
    }
}

void ChatDialog::slot_loading_chat_user()
{
    if (_b_loading) {
        return;
    }
    _b_loading = true;
    LoadingDlg *loadingDialog = new LoadingDlg(this);
    loadingDialog->show();
    addChatUserList();
    loadingDialog->deleteLater();
    _b_loading = false;
}

void ChatDialog::slot_addFriendApply(std::shared_ptr<AddFriendApply> addFriendApply)
{
    // 收到好友申请
    qDebug() << "slot_addFriendApply\n";
    qDebug() << "from: " << addFriendApply->_from_uid << ". desc: " << addFriendApply->_desc
             << ". name: " << addFriendApply->_name << ". icon: " << addFriendApply->_icon << "\n";
    // 判断用户是否已经发送过申请
    if (UserMgr::GetInstance()->AlreadyApply(addFriendApply->_from_uid)) {
        return;
    }
    std::shared_ptr<ApplyInfo> applyInfo = std::make_shared<ApplyInfo>();
    applyInfo->name = addFriendApply->_name;
    applyInfo->desc = addFriendApply->_desc;
    applyInfo->uid = addFriendApply->_from_uid;
    applyInfo->email = "";
    applyInfo->status = 0;
    applyInfo->sex = addFriendApply->_sex;
    applyInfo->icon = addFriendApply->_icon;
    UserMgr::GetInstance()->AddApplyInfo(applyInfo);
    ui->friend_apply_page->addNewApply(applyInfo);
}

void ChatDialog::slot_showFriendInfo(std::shared_ptr<FriendInfo> friendInfo)
{
    ui->chatdlg_right_stacked_widget->setCurrentWidget(ui->friend_info_page);
    ui->friend_info_page->setFriendInfo(friendInfo);
}

void ChatDialog::slot_jumpFriendChatPage(std::shared_ptr<FriendInfo> friendInfo)
{
    QListWidgetItem *item = makeChatUserFirst(friendInfo);
    // 设置当前项选中
    ui->chat_user_list->setCurrentItem(item);
    // 设置左侧显示聊天列表
    showChatPage(friendInfo);
}
// 有新消息
void ChatDialog::slot_hasNewTextMessage(std::shared_ptr<TextChatData> textChatData)
{
    int frienduid = textChatData->from_uid;
    QString message = textChatData->msg_content;
    QString send_time = textChatData->send_time;
    auto friendInfo = UserMgr::GetInstance()->GetFriend(frienduid);
    if (friendInfo == nullptr) {
        return;
    }
    // 存储消息
    friendInfo->chat_msgs.push_back(textChatData);
    friendInfo->last_msg = message;
    friendInfo->last_msg_time = send_time;
    //聊天列表第一个显示
    makeChatUserFirst(friendInfo, true);
    //聊天界面加入消息
    auto friendPageiter = _friendPages.find(frienduid);
    // 不存在与该用户的聊天界面
    if (friendPageiter == _friendPages.end()) {
        auto chatPage = std::make_shared<ChatPage>(ui->chat_msg_page);
        chatPage->adjustSize();
        chatPage->setFriendInfo(friendInfo);
        // 加入列表
        _friendPages[friendInfo->uid] = chatPage;
    } else {
        // 添加新消息
        friendPageiter.value()->addMessage(textChatData);
    }
}

void ChatDialog::slot_charUserClicked(std::shared_ptr<FriendInfo> friendInfo)
{
    // 左侧聊天列表设置选中
    auto iter = _chatUserMap.find(friendInfo->uid);
    QListWidgetItem *item = iter.value();
    ChatUserWid *chatUserWid = dynamic_cast<ChatUserWid *>(ui->chat_user_list->itemWidget(item));
    chatUserWid->setRedPointVisible(false);
    ui->chat_user_list->setCurrentItem(item);
    // 右侧显示聊天页面
    showChatPage(friendInfo);
}

void ChatDialog::paintEvent(QPaintEvent *event)
{
    // 创建一个QStyleOption对象
    QStyleOption opt;
    opt.initFrom(this);
    // 创建一个QPainter对象，用于绘制
    QPainter p(this);
    // 使用样式表绘制控件
    style()->drawPrimitive(QStyle::PE_Widget, &opt, &p, this);
    // 调用父类的paintEvent方法，处理其他绘制事件
    QDialog::paintEvent(event);
}

void ChatDialog::mousePressEvent(QMouseEvent *event)
{
    handleGlobalMousePress(event);
    QDialog::mousePressEvent(event);
}
